#include "homogeneous.h"
#include "../core/bbox.h"

HomogeneousVolume::HomogeneousVolume(const Transform *w2v, const Transform *v2w, Spectrum sa, Spectrum ss, Spectrum l, float fg, BBox e) {
	worldToVolume = w2v;
	volumeToWorld = v2w;
	sig_a = sa;
	sig_s = ss;
	g = fg;
	extent = e;
	le = l;
}

BBox HomogeneousVolume::WorldBound() const {
	return (*volumeToWorld)(extent);
}

bool HomogeneousVolume::IntersectP(const Ray &r, float *t0, float *t1) const {
	Ray ray = (*worldToVolume)(r);
	return extent.IntersectP(ray, t0, t1);
}

Spectrum HomogeneousVolume::sigma_a(const Point3 &p, const Vector3 &w) const {
	return extent.Inside((*worldToVolume)(p)) ? sig_a : 0.;
}

Spectrum HomogeneousVolume::sigma_s(const Point3 &p, const Vector3 &w) const {
	return extent.Inside((*worldToVolume)(p)) ? sig_s : 0.;
}

Spectrum HomogeneousVolume::sigma_t(const Point3 &p, const Vector3 &w) const {
	return extent.Inside((*worldToVolume)(p)) ? sig_a + sig_s : 0.;
}
Spectrum HomogeneousVolume::Lve(const Point3 &p, const Vector3 &w) const {
	return extent.Inside((*worldToVolume)(p)) ? le: 0.;
}
Spectrum HomogeneousVolume::tau(const Ray &ray, float step /* = 1.f */, float offset /* = 0.5 */) const {
	float t0, t1;
	if(!IntersectP(ray, &t0, &t1))
		return 0.;
	return Distance(ray(t0), ray(t1)) * (sig_a + sig_s);
}

float HomogeneousVolume::p(const Point3 &p, const Vector3 &wi, const Vector3 &wo) const {
	if (!extent.Inside((*worldToVolume)(p))) 
		return 0.;
	return PhaseHG(wi, wo, g);
}
